﻿using InterfaceLib;
using PluginNET;
using PluginNET.events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Plugin.NETTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // 使用接口来实例化插件管理器
            // 如果要对其它接口进行插件管理，
            // 那么可以创建另一个插件管理器的实例
            var pluginManager = new PluginManager<IInterface>();

            // 处理插件管理器发出的事件
            pluginManager.OnPlugin += PluginManager_OnPlugin;

            // 加载插件目录下的所的插件
            pluginManager.Load();

            // 开始监视新放进目录的插件
            pluginManager.Watch();


            Console.WriteLine("正在监视插件目录变动，按`Enter`退出");
            Console.ReadLine();
        }

        /// <summary>
        /// 处理插件管理器发出的事件
        /// </summary>
        /// <param name="sender">插件管理器的实例对象</param>
        /// <param name="e">事件数据</param>
        private static void PluginManager_OnPlugin(object sender, PluginEventArgs e)
        {
            switch (e.EventType)
            {
                // 加载程序集前的事件
                case PluginEventTypes.AssemblyLoading:
                    Console.WriteLine($"准备加载文件\"{e.FullName}\"");
                    break;
                case PluginEventTypes.AssemblyLoaded:
                    switch (e.ErrorType)
                    {
                        case PluginNET.error.PluginErrorTypes.None:
                            Console.WriteLine($"从文件\"{e.FullName}\"加载程序集\"{e.Assembly.FullName}\"成功");
                            break;
                        case PluginNET.error.PluginErrorTypes.InvalidManagedDllFile:
                            Console.WriteLine($"文件\"{e.FullName}\"不是有效的托管dll，可以查看异常:{e.Exception}");
                            break;
                        case PluginNET.error.PluginErrorTypes.ImplementionClassNotFound:
                            // 这里不会出现这个类型
                            break;
                        case PluginNET.error.PluginErrorTypes.IllegalClassDefinition:
                            // 这里不会出现这个类型
                            break;
                        case PluginNET.error.PluginErrorTypes.InstanceCreateFailed:
                            // 这里不会出现这个类型
                            break;
                        case PluginNET.error.PluginErrorTypes.Unkown:
                            // 这里不会出现这个类型
                            break;
                    }
                    break;
                case PluginEventTypes.ClassSearching:
                    switch (e.ErrorType)
                    {
                        case PluginNET.error.PluginErrorTypes.None:
                            // 这里不会出现这个类型
                            break;
                        case PluginNET.error.PluginErrorTypes.InvalidManagedDllFile:
                            // 这里不会出现这个类型
                            break;
                        case PluginNET.error.PluginErrorTypes.ImplementionClassNotFound:
                            Console.WriteLine($"在文件\"{e.FullName}\"中没有找到实现了指定接口的类");
                            break;
                        case PluginNET.error.PluginErrorTypes.IllegalClassDefinition:
                            Console.WriteLine($"在文件\"{e.FullName}\"中找到了实现指定接口的类，但是其声明不是class或声明为abstract或不是public");
                            break;
                        case PluginNET.error.PluginErrorTypes.InstanceCreateFailed:
                            // 这里不会出现这个类型
                            break;
                        case PluginNET.error.PluginErrorTypes.Unkown:
                            // 这里不会出现这个类型
                            break;
                    }
                    break;
                case PluginEventTypes.InstanceCreated:
                    switch (e.ErrorType)
                    {
                        case PluginNET.error.PluginErrorTypes.None:
                            Console.WriteLine($"在文件\"{e.FullName}\"中找到了实现指定接口的类\"{e.ClassType}\"，并且创建实例成功");

                            InvokePlugin(e.Instance);

                            break;
                        case PluginNET.error.PluginErrorTypes.InvalidManagedDllFile:
                            // 这里不会出现这个类型
                            break;
                        case PluginNET.error.PluginErrorTypes.ImplementionClassNotFound:
                              // 这里不会出现这个类型
                            break;
                        case PluginNET.error.PluginErrorTypes.IllegalClassDefinition:
                            Console.WriteLine($"在文件\"{e.FullName}\"中找到了实现指定接口的类，但是其声明不是class或声明为abstract或不是public");
                            break;
                        case PluginNET.error.PluginErrorTypes.InstanceCreateFailed:
                            Console.WriteLine($"在文件\"{e.FullName}\"中找到了实现指定接口的类\"{e.ClassType}\"，但是创建实例时抛出了异常:{e.Exception}");
                            break;
                        case PluginNET.error.PluginErrorTypes.Unkown:
                            // 仅创建实例成功，但是结果却为null时会出现这个
                            Console.WriteLine($"在文件\"{e.FullName}\"中找到了实现指定接口的类\"{e.ClassType}\"，创建实例成功，但是实例却是空引用(可能是不能转换成接口类型)");
                            break;
                    }
                    break;
            }
        }

        private static void InvokePlugin(object instance)
        {
            var plugin = instance as IInterface;

            Console.WriteLine(plugin.Method1());
            Console.WriteLine(plugin.Method2("哈哈哈哈"));
        }
    }
}
